
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>消费者组与消息消费机制 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>消费者组与消息消费机制 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是Kafka消费者组（Consumer Group），它的核心设计目标是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka中的消费者组是一个由多个消费者组成的逻辑集合，它们共同消费一个或多个主题中的消息。其核心设计目标是实现消息的负载均衡、容错性和并行消费能力，这也是Kafka支持高吞吐量和高可用性的核心机制之一。</div>
          </div>
          <div class="card-source">来源: 消费者组概述</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在Kafka消费者组中，消费者数量和主题分区数量之间存在怎样的关系？如果消费者数量超过分区数量会发生什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在一个消费者组中，每个分区只能被一个消费者消费。如果消费者数量小于分区数，一些消费者将负责多个分区。如果消费者数量大于分区数，那么多余的消费者将不会被分配到任何分区，处于空闲状态，不会消费任何消息。</div>
          </div>
          <div class="card-source">来源: 消费者组与Kafka分区的关系</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">Kafka消费者组如何实现容错性？当一个消费者发生故障时，系统会如何应对？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当某个消费者因故障退出时，Kafka会自动将其负责的分区重新分配给消费者组内其他存活的消费者。这个过程称为“再平衡”（Rebalance），它能保证在消费者发生故障时消息消费的连续性，不会中断。</div>
          </div>
          <div class="card-source">来源: 消费者组的容错性</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">什么是消费者“再平衡”（Rebalance）？通常在哪些情况下会触发？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">消费者“再平衡”是指Kafka重新为消费者组内的消费者分配分区的过程。它通常在以下四种情况下触发：1. 有新的消费者加入消费者组；2. 有消费者离开消费者组；3. 消费者发生故障或断开连接；4. 订阅的主题分区数量发生变化。</div>
          </div>
          <div class="card-source">来源: 消费者组的再平衡（Rebalance）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">Kafka如何保证消息的消费顺序？这种顺序性保证的范围是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka仅保证在单个分区（Partition）内消息的消费是按顺序的。对于一个消费者组，虽然每个消费者处理其分区内的消息时顺序是有保证的，但不同分区之间的消息消费顺序无法保证。这是为了实现高并发吞吐量而做出的权衡。</div>
          </div>
          <div class="card-source">来源: 消息消费的顺序与并发</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Kafka消费者提交偏移量（Offset）有哪两种主要方式？自动提交方式存在什么潜在风险？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka提供自动提交和手动提交两种偏移量提交方式。自动提交的潜在风险是：1. 偏移量可能在消费者成功处理消息之前就被提交，若此时消费者崩溃，可能导致消息丢失；2. 若消费者处理完消息后、在下一次自动提交前崩溃，可能导致消息重复消费。</div>
          </div>
          <div class="card-source">来源: 消费者的自动与手动提交偏移量</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">Kafka消费者采用的是“拉取（pull）”模型还是“推送（push）”模型来获取消息？这种模型有什么好处？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka消费者采用的是“拉取（pull）”模型，即消费者主动从Kafka集群中拉取消息。这种设计的好处在于，消费者可以根据自身的处理能力灵活控制消息的拉取速率，避免了被动接收导致的处理压力过大问题。</div>
          </div>
          <div class="card-source">来源: 消费者组的消息消费</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">Kafka将消费者组的偏移量（消费进度）存储在哪里？这种存储机制带来了什么好处？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka将消费者组的偏移量保存在一个名为 `__consumer_offsets` 的内部特殊主题中。这种持久化存储的好处是，即使消费者发生故障并重启，它也能够从上次成功提交的位置继续消费，从而避免丢失消息，保证了消费进度的可靠性。</div>
          </div>
          <div class="card-source">来源: 消费者组的协调与偏移量管理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Kafka为消费者组提供了哪些分区分配策略？请至少列举两种。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka支持多种分区分配策略，常见的包括：1. Range（范围分配）：为每个消费者分配连续的分区范围。2. RoundRobin（轮询分配）：将分区以轮询的方式逐一分配给消费者。3. Sticky（粘性分配）：在再平衡时尽量保持原有的分配，减少分区的移动。</div>
          </div>
          <div class="card-source">来源: 消费者组的分配策略</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
